package com.tedu.api.list;

import org.junit.Test;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;

/**
 * 迭代器：打印集合元素【接口】
 * 集合提供自己一套输出集合元素的方法---迭代器【类似for、增强for】
 * 包位置：java.util
 * Iterator     接口
 * 该接口是集合接口，提供遍历元素的相关操作：问、取、删
 *
 *
 * iterator()方法     返回值Iterator----Collection接口类已经存在方法
 * 作用：获取一个用于遍历当前集合迭代器的实现类实例
 *
 * 遍历规则：问、取、删（删不是必须操作）
 */
    public class Collection_iterator {
    @Test
    public void testIterator() {
        //创建集合
        Collection c1 = new ArrayList();
        c1.add("one");
        c1.add("two");
        c1.add("three");
        c1.add("four");
        c1.add("five");
        c1.add("six");
        //iterator()获取一个用于遍历当前集合迭代器的实现类实例
        Iterator it = c1.iterator();
        //理解：拿到集合所有元素，封装迭代器创建对象过程--理解迭代器实例
        //使用Iterator--获取集合的某个元素，规则：问、取、删
        //Iterator接口--hasNext() 获取集合元素
        //思考：如果说，300个元素  ----循环 while 次数不固定
        while (it.hasNext()) {//①问：集合是否有元素
        //迭代器集合：获取元素    |   next()元素
        String str = (String) it.next(); //②取：获取集合元素
       // System.out.println("集合迭代器：" + str);
        }
        //迭代器是否改变集合的元素内容
        System.out.println(c1);
    }

    /**试一试
     * 3.普通for---遍历c1集合       集合：size()  √
     * 语法：for(int i=0;i<c1.size();i++){}
     * 2.增强for---遍历c1集合       接受类型：Object   √
     * 语法：for(Object c:c1){}
     * 1.Iterator迭代器---集合提供接口   √
     */
    @Test
    public void testCollection(){
       //创建集合
        Collection c1=new ArrayList();
        c1.add("one");c1.add("two");c1.add("three");
        c1.add("four");c1.add("five");c1.add("six");
       //普通for  遍历集合(不建议)
        for (int i=0;i<c1.size();i++){
            System.out.println("普通for:"+i);  //打印

          }
        //增强for  遍历集合（建议）
        for(Object c:c1){
         System.out.println("增强for:"+c);
           }
     }
    /**
     * remove()    删除    Iterator迭代器 √    增强for
     * 作用：删除获取到的元素数据，提醒：问、取next方法【删】
     */
    @Test
    public void testRemove(){
        Collection c=new ArrayList();
        c.add("西游记");c.add("#");c.add("水浒");
        //需求：通过迭代器删除 #
          Iterator it=c.iterator();
        while (it.hasNext()){  //问：有没有元素
                String str=(String)it.next();   //取：有元素---打印元素
            //  c.remove("#");//Collection中存在remove()
            //删除一定是迭代器
            if("#".equals(str)){//如果#市我们拿到的str元素中的#，那么就能删除元素
                it.remove();
             }
        }
        System.out.println("迭代器的删除："+c);
        }
    /**
     * 增强for----底层使用Iterator迭代器【问、取、删】
     * c.remove("#")是Collection的删除方法，并不是迭代器方法
     * 增强for  需求： 删除集合中元素”#“
     */
        @Test
        public void testFor(){
        Collection c=new ArrayList();
        c.add("西游记");c.add("#");c.add("水浒");
        for(Object o:c){//类型  类型引用：集合引用
            String str=(String)o;//强转：拿到字符串类型
            /*if("#".equals(str)){
             c.remove("#");
        }*/
        }
        System.out.println("删除集合元素："+c);
        }

    /**
     * E----->element      泛型      JDK1.5新特性
     * 结合集合出现，约束集合的使用的类型[基本数据类型、引用类型、包装类]
     * 泛型的原型：Object，泛型是编译器认可的，JVM虚拟机并不认可
     * 使用泛型是告诉编译器应该吧泛型当成Object类型执行，便于编译器检查
     * 类型以及自动造型操控！
     *
     *
     * JDK1.5泛型使用：
     * Collection<类型：基本类型、引用类型、包装类> c
     * =new ArrayList<类型：基本类型、引用类型、包装类>();
     *
     *
     * JDK1.7泛型使用：
     *  Collection<类型：基本类型、引用类型、包装类> c
     *   =new ArrayList<>();
     *
     *
     * 泛型：自动推导   通配符：？   表示任意类型
     * Collection<类型：?> c
     * =new ArrayList<>();
     *
     *
     *
     * Collection<类型：? extends/super  父类/接口/类> c=new ArrayList<>();
     * 优点：保证类型安全，提高代码重用性和灵活性
     * ------限定集合传入对应类型
     *
     */


    @Test
    public void testType(){
        //针对泛型自动推导     通配符 ？
     Collection<?> c1=new ArrayList<>();
     c1.add(null);  //结论：并不是匹配所有类型，只能传空null，没意义


       Collection<String> c=new ArrayList<String>();
       c.add("123");c.add("456");c.add("789");
       //遍历Iterator
        Iterator<String> it=c.iterator();
        while (it.hasNext()){
            String str=it.next();
            System.out.println(str);
        }
    }
}








//------限定集合传入对应类型
  class Fruit{
  private String name;//成员变量

    public Fruit(String name) {//有参构造器
        this.name = name;
    }

    public String getName() {//方法
        return name;
    }

}
    class Apple extends Fruit{
    public Apple() {
        super("苹果");//调用父类的有参数的构造器，传入name名称
    }
}
    class Orange extends Fruit{
    public Orange() {
    super("橘子");//调用父类的有参数的构造器，传入name名称
    }
}
  //测试类---泛型上界
  class TestJob{
  //泛型上界  1.定义静态方法：制定泛型规则---集合中类型约定为Apple与Orange
  public static void printFruit(Collection<? extends Fruit> fruits){
  //2.增强for循环打印：集合中类型约定为Apple与Orange
  for(Fruit fruit:fruits){
  //3.方法能进入：Apple或Orange---打印名字
          System.out.println(fruit.getName());
        }
     }
  //主方法：测试功能
    public static void main(String[] args) {
    Collection<Apple> apples=new ArrayList<>();
    apples.add(new Apple()); //集合对象添加：Apple对象
    Collection<Orange> oranges=new ArrayList<>();
    oranges.add(new Orange());//集合对象添加：Orange对象
    printFruit(apples);  //测试：打印：苹果
    printFruit(oranges);
    //假设：西瓜
    /* Collection<String> strings=new ArrayList<>();
    strings.add(new String());
    printFruit(strings);    */
    }


    /**面试题：pop\poll\peek区别
     * pop        出栈获取队首                   Deque双端队列
     * poll       出队获取队首，删队列元素         Queue单端队列
     * peek       出队获取队首，保存队列元素       Queue单端队列
     */
}









